
// implements common handler and events for input from diverse sources
// define mouse button types
enum EMouseButtonType 
{
	eMouseButtonNone		= 0,
	eMouseButtonLeft		= 1,
	eMouseButtonMiddle		= 2,
	eMouseButtonRight		= 3,
	eMouseButtonWheel		= 4,
	eMaxMouseButtonType
};
// define mouse event types
enum EMouseEventType 
{
	eMouseEventNone				= 0,
	eMouseEventDown				= 1,
	eMouseEventUp				= 2,
	eMouseEventMove				= 3,
	eMouseEventClick			= 4,
	eMouseEventDoubleClick		= 5,
	eMaxMouseEventType, // must be last
};
// defines key event types
enum EKeyEventType 
{
	eKeyEventDown				= 0,
	eKeyEventUp					= 1,
	eMaxKeyEventType, // must be last
};
// defines action event types
enum EInputActionType 
{
	eInputActionMoveForward		= 0,
	eInputActionMoveBack		= 1,
	eInputActionTurnLeft		= 2,
	eInputActionTurnRight		= 3,
	eInputActionSlideLeft		= 4,
	eInputActionSlideRight		= 5,
	eInputActionJump			= 6,
	eInputActionToss			= 7,
	eInputActionReset			= 8,
	eInputActionQuit			= 9,
	eInputActionOrientation		= 10,
	eMaxInputActionType, // must be last
};
/*
// defines action event types
enum EActionEventType 
{
	eActionEventMoveForward		= 0,
	eActionEventMoveBack		= 1,
	eActionEventTurnLeft		= 2,
	eActionEventTurnRight		= 3,
	eActionEventSlideLeft		= 4,
	eActionEventSlideRight		= 5,
	eActionEventJump			= 6,
	eActionEventToss			= 7,
	eActionEventReset			= 8,
	eActionEventQuit			= 9,
	eActionEventOrientation		= 10,
	eMaxActionEventType, // must be last
};
*/

// class containing empty handlers for derived classes to override
class GameInputHandlersBase
{
public:
	//! called after processed HandleOrientationEvent for derived classes to override
	virtual bool	OnOrientationEvent( F32 f32RotX, F32 f32RotY, F32 f32RotZ  ){ return false; };
	//! called after processed HandleMouseEvent for derived classes to override
	virtual bool	OnMouseEvent( EMouseButtonType eMouseButType, EMouseEventType eMouseEventType, int iMouseXPos, int iMouseYPos  ){ return false; };
	//! called after processed HandleMouseWheel for derived classes to override
	virtual bool	OnMouseWheel( F32 f32MouseWheelDist ){ return false; };
	//! called after processed HandleKeyEvent for derived classes to override
	virtual bool	OnKeyEvent( EKeyEventType eKeyEventType, irr::EKEY_CODE eKey, int iFlags = 0 ){ return false; };

	//! called after processed HandleGuiEvent for derived classes to override
	virtual bool	OnGuiEvent( irr::gui::EGUI_EVENT_TYPE eGuiEventType, irr::gui::IGUIElement * poGuiElement ){ return false; };

	//! called after processing input
	virtual bool	OnInputAction( EInputActionType eInputActionType, F32 f32PosX, F32 f32PosY, F32 f32PosZ  ){ return false; };

	//! handle pause game
	virtual void	OnPause(){};

	//! handle resume game
	virtual void	OnResume(){};

	//! handle restart game
	virtual void	OnRestart(){};

};


class GameInputBase : public irr::IEventReceiver, public GameInputHandlersBase
{
public:
	//=== vars ===//
	VxIrrBase *		m_poIrrBase;
	BOOL			m_bInitialized;
	//=== key vars ===//
	bool			m_abKeys[ irr::KEY_KEY_CODES_COUNT];

	//=== mouse vars ===//
	bool			m_abMouseButState[ eMaxMouseButtonType ];
	bool			m_bMouseLocked;
	int				m_iMouseX;
	int				m_iMouseY;

	//=== orientation vars ===//
	irr::core::vector3df			m_v3fPhoneOrientation; 	// 3d physical orientation of phone

	//=== touch event vars ===//
	U32								m_u32TouchStartMs;		// start time in ms of touch
	F32								m_f32TouchDnX;			// x position of touch down event
	F32								m_f32TouchDnY;			// y position touch down event start 
	F32								m_f32TouchUpX; 			// x position of touch up event
	F32								m_f32TouchUpY; 			// y position of touch up event
	BOOL							m_bIsLongPress;			// if true is a long press
	F32								m_f32ScaledTouchSlopSquared; // touch distance slop based on screen size
	F32								m_bTouchHasNotMoved; 	// if true touch was not moved from start ( except within slop distance )
	irr::scene::ISceneNode* 		m_poTouchSceneNode;		// scene node touched during touch down event


	//=== constructor ===//
	GameInputBase();
	//=== destructor ===//
	~GameInputBase();

	//! startup
	virtual void	GameInputStartup( VxIrrBase * poIrrBase );

	//! shutdown
	virtual void	GameInputShutdown( void );

	//=== properties ===//
	//! return true if key is pressed
	bool	GetKeyState( irr::EKEY_CODE eKey ) const							{ return m_abKeys[ eKey ]; }
	//! set key press state
	void	SetKeyState( irr::EKEY_CODE eKey, bool bPressed )					{ m_abKeys[ eKey ] = bPressed; }

	//! return true if mouse button is pressed
	bool	GetMouseState( EMouseButtonType eMouseButton ) const				{ return m_abMouseButState[eMouseButton]; }
	//! set mouse button press state
	void	SetMouseState( EMouseButtonType eMouseButton, bool bPressed )		{ m_abMouseButState[eMouseButton] = bPressed; }
	//! get mouse locked state
	bool	GetMouseLocked( void) const											{ return m_bMouseLocked; }
	//! set mouse locked state
	void	SetMouseLocked( bool bValue )										{ m_bMouseLocked = bValue; }
	//! get mouse x position
	int		GetMouseX() const													{ return m_iMouseX; }
	//! set mouse x position
	void	SetMouseX( int iPosX )												{ m_iMouseX = iPosX; }
	//! get mouse y position
	int		GetMouseY() const													{ return m_iMouseY; }
	//! set mouse y position
	void	SetMouseY( int iPosY )												{ m_iMouseY = iPosY; }


	//=== overrides ===//
	//! override irrlicht event handler
	//! irrlicht passes all events through this handler, however, if
	//! the window is a external window none of the events are generated and
	//! also the android implementation has more event types than known by irrlicht 
	//! so we override then call the HandleXxxxxEvent that will be used in all implementations
	virtual bool OnEvent( const irr::SEvent& oIrrEvent );

	//=== methods ===//
	//! reset all inputs
	virtual void		ResetAllInput( void );
	//! return text description of key
	virtual const char * GetKeyName( irr::EKEY_CODE eKey );

	//! handle input from orientation sensor
	virtual bool	HandleOrientationEvent( F32 f32RotX, F32 f32RotY, F32 f32RotZ  );

	//! handle input from screen touch
	virtual bool	HandleTouchEvent( int iEvent, F32 f32PosX, F32 f32PosY );

	//! handle input from touch sensor or mouse
	virtual bool	HandleMouseEvent( EMouseButtonType eMouseButType, EMouseEventType eMouseEventType, int iMouseXPos, int iMouseYPos  );

	//! called after processed HandleMouseWheel for derived classes to override
	virtual bool	HandleMouseWheel( F32 f32MouseWheelDist );

	//! handle input from touch sensor or mouse
	virtual bool	HandleKeyEvent( EKeyEventType eKeyEventType, irr::EKEY_CODE eKey, int iFlags = 0 );

	//! handle event from irrlicht gui
	virtual bool	HandleGuiEvent( irr::gui::EGUI_EVENT_TYPE eEventType, irr::gui::IGUIElement * poGuiElement );

	//! handle input from touch sensor or mouse for derived classes to override
	virtual bool	HandleInputAction( EInputActionType eInputActionType, F32 f32PosX, F32 f32PosY, F32 f32PosZ  );

	//! handle pause game
	virtual void	HandlePause();

	//! handle resume game
	virtual void	HandleResume();

	//! handle restart game
	virtual void	HandleRestart();


};

